/**
 * 
 */
package designpattern.example.pos.barpay.unionall;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import designpattern.example.pos.barpay.unionall.entity.PayChannel;
import designpattern.example.pos.barpay.unionall.entity.PayChannelCharacteristic;
import designpattern.example.pos.barpay.unionall.entity.PosGoodsBusinessPayConfig;
import designpattern.example.pos.barpay.unionall.interfaces.ChannelPayInterface;

/**
 *
 *@类名称：BarcodePay.java
 *@类描述：联合支付主方法
 *@创建人：zhongy
 *@创建时间：2017年9月21日-上午11:26:00
 *@修改备注:
 *@version 
 */
public class BarcodePay implements ChannelPayInterface{

	static Logger log = Logger.getLogger(BarcodePay.class);
	private List<BarpayParams> list;
	private static final long QUERY_INTERVAL=1500L;
	public BarcodePay(List<BarpayParams> list){
		this.list=list;
	}
	private BarcodePay(){//私有化的原因：防止外部错误的调用空参构造器导致支付失败
		super();
	}
	
	
	/**
	 * XXX 支付方式的实习类和支付方式编号对应关系 目前先维护到map中
	 */
	private static Map<String,String> payMap=new HashMap<>();// 后期重构到数据库 key=payChannelCode,value=implClassName
	public static Map<String,String> payNameMap=new HashMap<>();// 后期重构到数据库 key=payChannelCode,value=支付渠道名称
	static{
		payMap.put(PayChannel.BARPAY_ALIPAY, "");//支付宝 com.unionall.barpay.paychannel.SubAlipay
		payMap.put(PayChannel.BARPAY_WEIXIN, "");//微信
		payMap.put(PayChannel.BARPAY_XUNLIAN_ALIPAY, "com.unionall.barpay.paychannel.SubXunLianAlipay");//迅联支付宝
		payMap.put(PayChannel.BARPAY_XUNLIAN_WEIXIN, "com.unionall.barpay.paychannel.SubXunLianWeiXin");//迅联微信
		payMap.put(PayChannel.BARPAY_WOPAY, "com.unionall.barpay.paychannel.SubWopay");//沃支付
		payMap.put(PayChannel.BARPAY_ICBC, "com.unionall.barpay.paychannel.SubICBCpay");//融e联
		payMap.put(PayChannel.BARPAY_BESTPAY, "com.unionall.barpay.paychannel.SubBestpay");//翼支付
		payMap.put(PayChannel.BARPAY_UNIONPAY, "com.unionall.barpay.paychannel.SubCUP");//银联
		payMap.put(PayChannel.BARPAY_CMCC_YUNPOS_ZHEJIANG, "com.unionall.barpay.paychannel.SubYunPosZheJiang");//浙江云pos
		payMap.put(PayChannel.BARPAY_CMCC_YUNPOS_TIANJIN, "com.unionall.barpay.paychannel.SubYunPosTianJin");//天津云pos
		payMap.put(PayChannel.BARPAY_CMCC_YUNPOS_JIDI, "com.unionall.barpay.paychannel.SubYunPosJiDi");//基地云pos
		payMap.put(PayChannel.BARPAY_TEST, "com.unionall.barpay.paychannel.SubTestpay");//测试支付渠道
		
		
		payNameMap.put(PayChannel.BARPAY_ALIPAY, "[支付宝]:");//支付宝
		payNameMap.put(PayChannel.BARPAY_WEIXIN, "[微信]:");//微信
		payNameMap.put(PayChannel.BARPAY_XUNLIAN_ALIPAY, "[迅联支付宝]:");//迅联支付宝
		payNameMap.put(PayChannel.BARPAY_XUNLIAN_WEIXIN, "[迅联微信]:");//迅联微信
		payNameMap.put(PayChannel.BARPAY_WOPAY, "[沃支付]:");//沃支付
		payNameMap.put(PayChannel.BARPAY_ICBC, "[融e联]:");//融e联
		payNameMap.put(PayChannel.BARPAY_BESTPAY, "[翼支付]:");//翼支付
		payNameMap.put(PayChannel.BARPAY_UNIONPAY, "[银联]:");//银联
		payNameMap.put(PayChannel.BARPAY_CMCC_YUNPOS_ZHEJIANG, "[浙江云pos]:");//浙江云pos
		payNameMap.put(PayChannel.BARPAY_CMCC_YUNPOS_TIANJIN, "[天津云pos]:");//天津云pos
		payNameMap.put(PayChannel.BARPAY_CMCC_YUNPOS_JIDI, "[基地云pos]:");//基地云pos
		payNameMap.put(PayChannel.BARPAY_TEST, "[测试支付]:");//测试支付渠道

	}
	
	

	
	
	public void barpay()  {
		/**
		 * step1、参数检查
		 * step2、构建线程池
		 * step3、等待支付结果 
		 */
		int channelNum=list.size();
		ExecutorService executor = Executors.newFixedThreadPool(channelNum);  
		CyclicBarrier barr=new CyclicBarrier(channelNum);
		for(BarpayParams params:list){
			//XXX 等待重构
			PosGoodsBusinessPayConfig config=params.getConfig();
			String payChannelCode=config.getPayChannelCode();
			String payClassStr=payMap.get(payChannelCode);
			if(StringUtils.isBlank(payClassStr)){//不支持的支付方式
				log.info("不支持的支付方式");
				return;
			}
			try{
				params.setLogpre(payNameMap.get(payChannelCode));
				Runnable r=	(Runnable) Class.forName(payClassStr).getConstructor(BarpayParams.class,CyclicBarrier.class).newInstance(params,barr);
				executor.submit(new Thread(r));
			}catch(Exception e){
				log.info("反射调用构造器失败",e);//一般不会出现
				return;
			}
		}
		executor.shutdown();//关闭线程池
		while(true){
			boolean allComplete=true;
			for(BarpayParams params:list){
				allComplete=(allComplete && params.isComplete());
			}
			//log.debug("所有支付渠道执行结果："+allComplete)
			try {
				Thread.sleep(QUERY_INTERVAL);
			} catch (InterruptedException e) {
				log.info("联合支付线程休息异常："+e.getMessage(),e);
				
			}
			if(allComplete){
				log.info("联合支付线程执行完毕");
				break;
			}
		}
	}
	@Override
	public boolean checkParams(PosGoodsBusinessPayConfig config){
		/**
		 * step1、获取具体的支付渠道实现类
		 * step2、调用反射初始化
		 * step3、调用检查的方法
		 * step4、返回结果
		 */
		String payChannelCode=config.getPayChannelCode();
		String payClassStr=payMap.get(payChannelCode);
		if(StringUtils.isBlank(payClassStr)){//不支持的支付方式
			log.info("检查参数,无反射类,payChannelCode="+payChannelCode);
			return false;
		}
		PayChannelCharacteristic pcc=null;
		try {
			pcc = config.getPcc();
		} catch (Exception e1) {
			
		}
		//支付渠道特征值
		if(pcc==null||pcc.getJifenProductId()==null||pcc.getJifenProductId().longValue()<1L){
			log.info("支付渠道特征采购商产品未配置,payChannelCode="+payChannelCode);
			return false;
		}
		ChannelPayInterface cpimpl;
		try {
			cpimpl = (ChannelPayInterface) Class.forName(payClassStr).newInstance();
			return cpimpl.checkParams(config);
		} catch (Exception e) {
			log.error("检查参数,反射初始化失败",e);
		}
		return false;
	}
	/**
	 * 
	 *@描述  ：检查支付渠道参数
	 *@创建人：zhongy
	 *@创建时间：2017年9月24日 下午3:35:41
	 *@修改人：
	 *@修改时间：
	 *@修改描述：
	 *@param config
	 *@return
	 */
	public static boolean checkParamsByPayConfig(final PosGoodsBusinessPayConfig config){
		return new  BarcodePay().checkParams(config);
	}

}
